#!/usr/bin/env python3
"""
ONVIF摄像头管理系统主程序
提供命令行界面进行设备发现和监控
"""

import sys
import time
from pathlib import Path

# 添加项目根目录到Python路径
sys.path.insert(0, str(Path(__file__).parent))

from src.device_manager import DeviceManager
from src.utils.config import Config
from src.utils.logger import setup_logger, get_logger


class CamInfoCLI:
    """命令行界面"""
    
    def __init__(self):
        # 加载配置
        self.config = Config()
        
        # 设置日志
        setup_logger(self.config.logging)
        self.logger = get_logger(__name__)
        
        # 初始化设备管理器
        self.device_manager = DeviceManager(self.config)
        
        self.logger.info(f"ONVIF摄像头管理系统启动 - {self.config.app.name} v{self.config.app.version}")
    
    def show_banner(self):
        """显示程序横幅"""
        print("=" * 60)
        print(f"  {self.config.app.name} v{self.config.app.version}")
        print("  ONVIF网络摄像头发现和监控系统")
        print("=" * 60)

        # 显示Prometheus信息
        if (hasattr(self.device_manager, 'prometheus_exporter') and
            self.device_manager.prometheus_exporter and
            self.device_manager.prometheus_exporter.is_server_running()):
            prometheus_url = self.device_manager.prometheus_exporter.get_metrics_url()
            print(f"📊 Prometheus指标服务器: {prometheus_url}")
            print()
        print()
    
    def show_menu(self):
        """显示主菜单"""
        print("主菜单:")
        print("1. 发现ONVIF设备")
        print("2. 探测指定IP设备")
        print("3. 监控所有设备")
        print("4. 监控指定设备")
        print("5. 显示设备列表")
        print("6. 显示设备详情")
        print("7. 显示统计信息")
        print("8. 清空所有设备")
        print("9. 连续监控模式")
        print("10. 自动更新模式")
        print("0. 退出")
        print("-" * 40)
    
    def discover_devices(self):
        """发现设备"""
        print("\n正在发现ONVIF设备...")
        print(f"扫描网络段: {', '.join(self.config.discovery.network_ranges)}")
        print(f"超时时间: {self.config.discovery.timeout}秒")
        print()
        
        devices = self.device_manager.discover_devices()
        
        if devices:
            print(f"发现 {len(devices)} 个ONVIF设备:")
            print("-" * 80)
            print(f"{'序号':<4} {'IP地址':<15} {'端点URL':<40} {'状态':<10}")
            print("-" * 80)
            
            for i, device in enumerate(devices, 1):
                print(f"{i:<4} {device.ip_address:<15} {device.endpoint_url:<40} {device.status.value:<10}")
        else:
            print("未发现任何ONVIF设备")
            print("\n请检查:")
            print("- 网络中是否有ONVIF设备")
            print("- 设备是否启用了ONVIF服务")
            print("- 防火墙是否允许多播通信")
            print("- 网络段配置是否正确")
    
    def probe_device(self):
        """探测指定设备"""
        ip_address = input("\n请输入要探测的IP地址: ").strip()
        
        if not ip_address:
            print("IP地址不能为空")
            return
        
        print(f"\n正在探测设备: {ip_address}")
        device = self.device_manager.probe_device(ip_address)
        
        if device:
            print("探测成功!")
            print(f"设备ID: {device.device_id}")
            print(f"IP地址: {device.ip_address}")
            print(f"端点URL: {device.endpoint_url}")
            print(f"端口: {device.port}")
            print(f"状态: {device.status.value}")
        else:
            print("探测失败，该IP地址可能不是ONVIF设备")
    
    def monitor_all_devices(self):
        """监控所有设备"""
        devices = self.device_manager.get_device_list()
        
        if not devices:
            print("\n没有可监控的设备，请先发现设备")
            return
        
        print(f"\n正在监控 {len(devices)} 个设备...")
        print()
        
        results = self.device_manager.monitor_all_devices()
        
        if results:
            print("监控结果:")
            print("-" * 100)
            print(f"{'IP地址':<15} {'状态':<12} {'延迟(ms)':<10} {'丢包率(%)':<10} {'抖动(ms)':<10} {'开放端口':<20}")
            print("-" * 100)
            
            for result in results:
                device = self.device_manager.get_device(result.device_id)
                if device and result.network_metrics:
                    print(f"{device.ip_address:<15} {result.status.value:<12} "
                          f"{result.network_metrics.latency_ms:<10.2f} "
                          f"{result.network_metrics.packet_loss_rate:<10.1f} "
                          f"{result.network_metrics.jitter_ms:<10.2f} "
                          f"{','.join(map(str, result.open_ports)):<20}")
                else:
                    print(f"{device.ip_address if device else 'Unknown':<15} {result.status.value:<12} "
                          f"{'N/A':<10} {'N/A':<10} {'N/A':<10} {'N/A':<20}")
    
    def monitor_specific_device(self):
        """监控指定设备"""
        devices = self.device_manager.get_device_list()
        
        if not devices:
            print("\n没有可监控的设备，请先发现设备")
            return
        
        print("\n可用设备:")
        for i, device in enumerate(devices, 1):
            print(f"{i}. {device.ip_address} ({device.status.value})")
        
        try:
            choice = int(input("\n请选择要监控的设备编号: "))
            if 1 <= choice <= len(devices):
                device = devices[choice - 1]
                print(f"\n正在监控设备: {device.ip_address}")
                
                result = self.device_manager.monitor_device(device.device_id)
                
                if result and result.network_metrics:
                    print("监控结果:")
                    print(f"状态: {result.status.value}")
                    print(f"延迟: {result.network_metrics.latency_ms:.2f}ms")
                    print(f"丢包率: {result.network_metrics.packet_loss_rate:.1f}%")
                    print(f"抖动: {result.network_metrics.jitter_ms:.2f}ms")
                    print(f"开放端口: {', '.join(map(str, result.open_ports))}")
                else:
                    print(f"监控失败: {result.error_message if result else '未知错误'}")
            else:
                print("无效的选择")
        except ValueError:
            print("请输入有效的数字")
    
    def show_device_list(self):
        """显示设备列表"""
        online_devices = self.device_manager.get_device_list()
        offline_devices = list(self.device_manager.offline_devices.values())
        total_devices = len(online_devices) + len(offline_devices)

        if total_devices == 0:
            print("\n没有发现任何设备")
            return

        print(f"\n设备列表 (在线: {len(online_devices)}, 离线: {len(offline_devices)}, 总计: {total_devices}):")

        # 显示在线设备
        if online_devices:
            print("\n📱 在线设备:")
            print("-" * 130)
            print(f"{'序号':<4} {'IP地址':<15} {'状态':<12} {'厂商':<15} {'型号':<15} {'最后发现时间':<20} {'端点URL':<30}")
            print("-" * 130)

            for i, device in enumerate(online_devices, 1):
                last_seen = device.last_seen.strftime("%Y-%m-%d %H:%M:%S") if device.last_seen else "未知"
                print(f"{i:<4} {device.ip_address:<15} {device.status.value:<12} "
                      f"{device.manufacturer:<15} {device.model:<15} {last_seen:<20} {device.endpoint_url:<30}")

        # 显示离线设备
        if offline_devices:
            print("\n📴 离线设备 (保留5分钟):")
            print("-" * 130)
            print(f"{'序号':<4} {'IP地址':<15} {'状态':<12} {'厂商':<15} {'型号':<15} {'离线时间':<20} {'剩余保留时间':<15}")
            print("-" * 130)

            from datetime import datetime
            current_time = datetime.now()

            for i, device in enumerate(offline_devices, 1):
                device_id = device.device_id
                offline_time = self.device_manager.offline_timestamps.get(device_id)

                if offline_time:
                    offline_duration = (current_time - offline_time).total_seconds()
                    remaining_seconds = max(0, (5 * 60) - offline_duration)
                    remaining_minutes = int(remaining_seconds // 60)
                    remaining_secs = int(remaining_seconds % 60)
                    remaining_str = f"{remaining_minutes}:{remaining_secs:02d}"
                    offline_time_str = offline_time.strftime("%Y-%m-%d %H:%M:%S")
                else:
                    remaining_str = "未知"
                    offline_time_str = "未知"

                print(f"{i:<4} {device.ip_address:<15} {'离线':<12} "
                      f"{device.manufacturer:<15} {device.model:<15} {offline_time_str:<20} {remaining_str:<15}")
    
    def show_device_details(self):
        """显示设备详情"""
        devices = self.device_manager.get_device_list()
        
        if not devices:
            print("\n没有可查看的设备")
            return
        
        print("\n可用设备:")
        for i, device in enumerate(devices, 1):
            print(f"{i}. {device.ip_address}")
        
        try:
            choice = int(input("\n请选择要查看的设备编号: "))
            if 1 <= choice <= len(devices):
                device = devices[choice - 1]
                
                print(f"\n设备详情:")
                print(f"设备ID: {device.device_id}")
                print(f"IP地址: {device.ip_address}")
                print(f"端点URL: {device.endpoint_url}")
                print(f"端口: {device.port}")
                print(f"厂商: {device.manufacturer or '未知'}")
                print(f"型号: {device.model or '未知'}")
                print(f"序列号: {device.serial_number or '未知'}")
                print(f"MAC地址: {device.mac_address or '未知'}")
                print(f"当前状态: {device.status.value}")
                print(f"首次发现: {device.first_discovered.strftime('%Y-%m-%d %H:%M:%S') if device.first_discovered else '未知'}")
                print(f"最后发现: {device.last_seen.strftime('%Y-%m-%d %H:%M:%S') if device.last_seen else '未知'}")
                
                # 显示状态历史
                history = self.device_manager.get_device_status_history(device.device_id, 5)
                if history:
                    print(f"\n最近状态历史 (最近5条):")
                    for record in history:
                        timestamp = record.timestamp.strftime("%H:%M:%S") if record.timestamp else "未知"
                        print(f"  {timestamp} - {record.status.value}")
            else:
                print("无效的选择")
        except ValueError:
            print("请输入有效的数字")
    
    def show_statistics(self):
        """显示统计信息"""
        stats = self.device_manager.get_statistics()

        print("\n📊 系统统计信息:")
        print("-" * 50)
        print(f"总设备数: {stats['total_devices']}")
        print(f"在线设备: {stats['online_devices']}")
        print(f"离线设备: {stats['offline_devices']}")
        print(f"  └─ 保留中的离线设备: {stats['offline_retention_count']}")
        print(f"网络异常: {stats['network_issue_devices']}")
        print(f"服务异常: {stats['service_issue_devices']}")
        print(f"未知状态: {stats['unknown_devices']}")
        print(f"在线率: {stats['uptime_percentage']:.1f}%")
        print(f"离线设备保留时间: {stats['offline_retention_minutes']} 分钟")

        # 显示Prometheus信息
        if hasattr(self.device_manager, 'prometheus_exporter') and self.device_manager.prometheus_exporter:
            print(f"\n📈 Prometheus监控:")
            print(f"指标服务器: http://localhost:9098/metrics")
            print(f"监控状态: 运行中")
    
    def clear_devices(self):
        """清空所有设备"""
        confirm = input("\n确定要清空所有设备吗？(y/N): ").strip().lower()
        
        if confirm == 'y':
            self.device_manager.clear_all_devices()
            print("所有设备已清空")
        else:
            print("操作已取消")
    
    def continuous_monitor(self):
        """连续监控模式"""
        devices = self.device_manager.get_device_list()
        
        if not devices:
            print("\n没有可监控的设备，请先发现设备")
            return
        
        interval = self.config.monitoring.ping.interval
        print(f"\n进入连续监控模式 (间隔: {interval}秒)")
        print("按 Ctrl+C 退出连续监控")
        print()
        
        try:
            while True:
                print(f"\n[{time.strftime('%Y-%m-%d %H:%M:%S')}] 监控中...")
                results = self.device_manager.monitor_all_devices()
                
                online_count = sum(1 for r in results if r.status.value == 'online')
                offline_count = sum(1 for r in results if r.status.value == 'offline')
                
                print(f"监控完成 - 在线: {online_count}, 离线: {offline_count}")
                
                # 等待下次监控
                time.sleep(interval)
                
        except KeyboardInterrupt:
            print("\n\n退出连续监控模式")

    def auto_update_mode(self):
        """自动更新模式"""
        devices = self.device_manager.get_device_list()

        if not devices:
            print("\n没有可更新的设备，请先发现设备")
            return

        # 获取更新频率
        print("\n自动更新模式设置:")
        print("请选择更新频率:")
        print("1. 2秒")
        print("2. 3秒")
        print("3. 5秒")
        print("4. 10秒")
        print("5. 自定义 (2-10秒)")

        try:
            freq_choice = input("请选择频率 (1-5): ").strip()

            if freq_choice == '1':
                interval = 2
            elif freq_choice == '2':
                interval = 3
            elif freq_choice == '3':
                interval = 5
            elif freq_choice == '4':
                interval = 10
            elif freq_choice == '5':
                while True:
                    try:
                        interval = int(input("请输入自定义频率 (2-10秒): "))
                        if 2 <= interval <= 10:
                            break
                        else:
                            print("频率必须在2-10秒之间")
                    except ValueError:
                        print("请输入有效的数字")
            else:
                print("无效的选择，使用默认频率5秒")
                interval = 5
        except (ValueError, KeyboardInterrupt):
            print("使用默认频率5秒")
            interval = 5

        # 选择更新模式
        print(f"\n选择更新模式 (更新频率: {interval}秒):")
        print("1. 快速模式 - 只更新现有状态，不进行网络检查")
        print("2. 完整模式 - 进行完整的网络监控检查")

        try:
            update_mode_choice = input("请选择更新模式 (1-2): ").strip()
        except KeyboardInterrupt:
            print("\n操作已取消")
            return

        if update_mode_choice not in ['1', '2']:
            print("无效的选择，使用快速模式")
            update_mode_choice = '1'

        fast_mode = (update_mode_choice == '1')

        # 选择显示模式
        print(f"\n选择显示模式:")
        print("1. 简洁模式 - 只显示统计信息")
        print("2. 详细模式 - 显示所有设备状态")
        print("3. 表格模式 - 显示设备状态表格")

        try:
            display_choice = input("请选择显示模式 (1-3): ").strip()
        except KeyboardInterrupt:
            print("\n操作已取消")
            return

        if display_choice not in ['1', '2', '3']:
            print("无效的选择，使用简洁模式")
            display_choice = '1'

        mode_name = '快速' if fast_mode else '完整'
        display_name = '简洁' if display_choice == '1' else '详细' if display_choice == '2' else '表格'
        print(f"\n进入自动更新模式 (频率: {interval}秒, 更新: {mode_name}, 显示: {display_name})")
        print("按 Ctrl+C 退出自动更新")
        print("=" * 80)

        try:
            update_count = 0
            while True:
                update_count += 1
                current_time = time.strftime('%Y-%m-%d %H:%M:%S')

                if fast_mode:
                    # 快速模式：只获取当前状态，不进行网络检查
                    online_devices = list(self.device_manager.devices.values())
                    offline_devices = list(self.device_manager.offline_devices.values())
                    all_devices = online_devices + offline_devices

                    # 创建简单的状态结果
                    from src.models.device import DeviceStatusRecord
                    results = []
                    for device in all_devices:
                        status_record = DeviceStatusRecord(
                            device_id=device.device_id,
                            status=device.status,
                            network_metrics=None,
                            open_ports=[]
                        )
                        results.append(status_record)

                    # 计算统计信息
                    online_count = len([d for d in all_devices if d.status.value == 'online'])
                    offline_count = len([d for d in all_devices if d.status.value == 'offline'])
                    network_issue_count = len([d for d in all_devices if d.status.value == 'network_issue'])
                    service_issue_count = len([d for d in all_devices if d.status.value == 'service_issue'])
                    unknown_count = len([d for d in all_devices if d.status.value == 'unknown'])
                    total_count = len(all_devices)
                else:
                    # 完整模式：执行完整的网络监控
                    results = self.device_manager.monitor_all_devices()

                    # 计算统计信息
                    online_count = sum(1 for r in results if r.status.value == 'online')
                    offline_count = sum(1 for r in results if r.status.value == 'offline')
                    network_issue_count = sum(1 for r in results if r.status.value == 'network_issue')
                    service_issue_count = sum(1 for r in results if r.status.value == 'service_issue')
                    unknown_count = sum(1 for r in results if r.status.value == 'unknown')
                    total_count = len(results)

                # 清屏（可选）
                if update_count > 1:
                    print("\n" + "=" * 80)

                print(f"[更新 #{update_count}] {current_time}")

                if display_choice == '1':
                    # 简洁模式
                    print(f"📊 设备状态: 总计 {total_count} | 在线 {online_count} | 离线 {offline_count} | 网络异常 {network_issue_count} | 服务异常 {service_issue_count} | 未知 {unknown_count}")
                    if total_count > 0:
                        uptime_rate = (online_count / total_count) * 100
                        print(f"📈 在线率: {uptime_rate:.1f}%")

                elif display_choice == '2':
                    # 详细模式
                    print(f"📊 设备状态统计:")
                    print(f"   总设备数: {total_count}")
                    print(f"   在线设备: {online_count}")
                    print(f"   离线设备: {offline_count}")
                    print(f"   网络异常: {network_issue_count}")
                    print(f"   服务异常: {service_issue_count}")
                    print(f"   未知状态: {unknown_count}")
                    if total_count > 0:
                        uptime_rate = (online_count / total_count) * 100
                        print(f"   在线率: {uptime_rate:.1f}%")

                    # 显示有问题的设备
                    problem_devices = [r for r in results if r.status.value != 'online']
                    if problem_devices:
                        print(f"\n⚠️  问题设备 ({len(problem_devices)}个):")
                        for result in problem_devices:
                            device = self.device_manager.get_device(result.device_id)
                            if device:
                                print(f"   {device.ip_address} - {result.status.value}")

                elif display_choice == '3':
                    # 表格模式
                    print(f"📊 设备状态表格:")
                    print("-" * 80)
                    print(f"{'IP地址':<15} {'状态':<12} {'延迟(ms)':<10} {'丢包率(%)':<10} {'抖动(ms)':<10}")
                    print("-" * 80)

                    for result in results:
                        device = self.device_manager.get_device(result.device_id)
                        if device:
                            if result.network_metrics:
                                latency = f"{result.network_metrics.latency_ms:.1f}"
                                packet_loss = f"{result.network_metrics.packet_loss_rate:.1f}"
                                jitter = f"{result.network_metrics.jitter_ms:.1f}"
                            else:
                                latency = packet_loss = jitter = "N/A"

                            # 根据状态添加状态图标
                            status_icon = {
                                'online': '🟢',
                                'offline': '🔴',
                                'network_issue': '🟡',
                                'service_issue': '🟠',
                                'unknown': '⚪'
                            }.get(result.status.value, '❓')

                            status_display = f"{status_icon} {result.status.value}"
                            print(f"{device.ip_address:<15} {status_display:<12} {latency:<10} {packet_loss:<10} {jitter:<10}")

                    print("-" * 80)
                    print(f"总计: {total_count} | 在线: {online_count} | 离线: {offline_count}")

                # 等待下次更新
                print(f"\n⏱️  下次更新: {interval}秒后...")
                time.sleep(interval)

        except KeyboardInterrupt:
            print(f"\n\n✅ 退出自动更新模式 (共执行了 {update_count} 次更新)")
    
    def run(self):
        """运行主程序"""
        self.show_banner()
        
        while True:
            try:
                self.show_menu()
                choice = input("请选择操作 (0-10): ").strip()

                if choice == '1':
                    self.discover_devices()
                elif choice == '2':
                    self.probe_device()
                elif choice == '3':
                    self.monitor_all_devices()
                elif choice == '4':
                    self.monitor_specific_device()
                elif choice == '5':
                    self.show_device_list()
                elif choice == '6':
                    self.show_device_details()
                elif choice == '7':
                    self.show_statistics()
                elif choice == '8':
                    self.clear_devices()
                elif choice == '9':
                    self.continuous_monitor()
                elif choice == '10':
                    self.auto_update_mode()
                elif choice == '0':
                    print("\n感谢使用ONVIF摄像头管理系统！")
                    break
                else:
                    print("\n无效的选择，请重新输入")
                
                if choice != '0':
                    input("\n按回车键继续...")
                    print()
                
            except KeyboardInterrupt:
                print("\n\n程序被用户中断")
                break
            except Exception as e:
                self.logger.error(f"程序运行错误: {e}")
                print(f"\n发生错误: {e}")
                input("按回车键继续...")


def main():
    """主函数"""
    try:
        cli = CamInfoCLI()
        cli.run()
    except Exception as e:
        print(f"程序启动失败: {e}")
        sys.exit(1)


if __name__ == "__main__":
    main()
